//
import { Color, PlaneGeometry, Mesh, ShaderMaterial, Vector3, DoubleSide, TextureLoader } from "three";
import Effect from "./Effect";
import TrailLinkShader from "../../renderExtension/Material/shaders/chunks/TrailLinkShader";
import { Point } from "../../renderExtension/types/Point";
import Const from "../../application/constants/Const";
import Events from "../../application/constants/Events";
import Helper from "../../utils/Helper";

/**
* 轨迹围栏
*/
export default class TrailLink extends Effect {
    private QuadsMesh: Mesh;
    private uniforms;
    public width;
    public segmentLen;
    public pathArray;
    public pathLen = 0.0;
    public curSegmentNo;
    public curSegmentNoStartLen;
    public points;
    public alpha;
    public center;
    public color;
    public time;
    private texture = '../resources/images/TrailLink.png';

    /**
     * @param cfg 配置参数
     * @config cfg.width 宽度
     * @config cfg.color 颜色
     * @config cfg.colorObject 颜色
     * @config cfg.pathArray 轨迹信息
     * @config cfg.curSegmentNo 线段编号
     * @config cfg.points 轨迹信息
     * @config cfg.time 扫描速度
     * @config cfg.displayOnTop 是否展示在最上层
    */
    constructor(cfg) {
        super();
        this.width = cfg.width ? cfg.width : 10;
        this.color = (cfg.color === undefined) ? '#ff0000' : cfg.color;
        this.pathArray = this.changePositionEPSGType(cfg.pathArray);
        this.curSegmentNo = cfg.curSegmentNo;
        this.points = this.changePositionEPSGType(cfg.points);
        this.calcPathLen();
        this.calcCurSegement();
        this.time = cfg.time ? cfg.time : 5000;
        this.displayOnTop = cfg.displayOnTop ? cfg.displayOnTop : false;
        if (cfg.texture) {
            this.texture = cfg.texture;
        }
        this.init();
    }

    protected changePositionEPSGType(points: any) {
        let newPoints = [];
        if (points && Array.isArray(points)) {
            points.forEach(point => {
                if (point instanceof Point) {
                    let currentPoint = point.clone();
                    // currentPoint.z = 0;
                    let element = currentPoint.toEPSGWeb();
                    newPoints.push(element);
                }
            });
        }
        return newPoints;
    }

    private setUniforms() {
        var texture = new TextureLoader().load(this.texture)
        this.uniforms = {
            map: {
                value: texture
            },
            pathLen: { value: this.pathLen },
            curSegementNo: { value: this.curSegmentNo },
            curSegmentNoStartLen: { value: this.curSegmentNoStartLen },
            segmentLen: { value: this.segmentLen },
            v_color: { type: 'c', value: new Vector3(this.color.r, this.color.g, this.color.b) },
            time: { type: 'f', value: 1.0 },
        };
    }

    private init() {
        let width = this.width;
        let SegmentLen = this.segmentLen;
        this.setUniforms();
        var material = new ShaderMaterial({
            uniforms: this.uniforms,
            vertexShader: TrailLinkShader.getVertexShader(),
            fragmentShader: TrailLinkShader.getFragmentShader(),
            side: DoubleSide,
            depthTest: false,
            transparent: true,
        });

        let geo = new PlaneGeometry(SegmentLen, width);
        let centerVector = new Point(this.center[0], this.center[1], this.center[2]);
        this.QuadsMesh = new Mesh(geo, material);
        this.QuadsMesh.position.set(centerVector.x, centerVector.y, centerVector.z);
        this.QuadsMesh.rotation['z'] = this.alpha;
        if (this.displayOnTop) {
            //this.QuadsMesh.material.depthTest = false;
            this.QuadsMesh.renderOrder = 99;
        }
        this.QuadsMesh.userData.isEffectMesh = true;
        this.QuadsMesh.userData.effect = this;
        this.add(this.QuadsMesh);
        this.register();
    }

    /**
    * 轨迹围栏总长度
    */
    protected calcPathLen() {
        if (this.pathArray.length >= 2) {
            for (var i = 0; i < (this.pathArray.length - 1); i++) {
                var deltaY = this.pathArray[i + 1].y - this.pathArray[i].y;
                var deltaX = this.pathArray[i + 1].x - this.pathArray[i].x;
                if (Math.abs(deltaX) <= 0.00001) {
                    if (deltaX > 0.0) {
                        deltaX = 0.00001;
                    }
                    else {
                        deltaX = -0.00001;
                    }
                }
                if (this.curSegmentNo === i) {
                    this.curSegmentNoStartLen = this.pathLen;
                }
                this.pathLen += Math.sqrt(deltaY * deltaY + deltaX * deltaX);
            }

        }
    }

    /**
    * 某轨迹围栏段的长度
    */
    protected calcCurSegement() {
        this.center = [(this.points[0].x + this.points[1].x) / 2, (this.points[0].y + this.points[1].y) / 2, (this.points[0].z + this.points[1].z) / 2];
        var deltaY = this.points[1].y - this.points[0].y;
        var deltaX = this.points[1].x - this.points[0].x;
        if (Math.abs(deltaX) <= 0.00001) {
            if (deltaX > 0.0) {
                deltaX = 0.00001;
            }
            else {
                deltaX = -0.00001;
            }
        }

        if (deltaX >= 0) {
            this.alpha = Math.atan(deltaY / deltaX);
        }
        else {
            this.alpha = Math.PI + Math.atan(deltaY / deltaX);
        }

        this.segmentLen = Math.sqrt(deltaY * deltaY + deltaX * deltaX);
    }

    public setPosition(position) {
        this.QuadsMesh.position.set(position.x, position.y, position.z);
    }

    protected register() {
        super.register();
        this.app.on(Events.Render, this.updateUniforms, this);
    }

    public dispose() {
        this.app.off(Events.Render, this.updateUniforms, this);
        this.remove(this.QuadsMesh);
    }

    protected updateUniforms() {
        var now = new Date().getTime();
        var n = (now % this.time) / (this.time * 1.0);
        this.uniforms.time.value = n;
    }
}
